/*
 * 文件名： ApayPabBankServiceImpl.java
 * 
 * 工程名称: bis-bank-pab
 *
 * Gopay
 *
 * 创建日期： 2017年8月14日
 *
 * Copyright(C) 2017, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.pab.apay.impl;

import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.gopay.bis.pab.apay.operation.PabApayHelper;
import com.gopay.bis.pab.apay.operation.Transport;
import com.gopay.common.constants.bank.PabConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.pab.agpay.PabTransResMsg;
import com.gopay.common.domain.bank.pab.agpay.req.MerchantConfig;
import com.gopay.common.domain.bank.pab.agpay.res.MerchantAddResMsg;
import com.gopay.common.domain.bank.pab.agpay.res.PayCancelResMsg;
import com.gopay.common.domain.bank.pab.agpay.res.PayOrderResMsg;
import com.gopay.common.domain.bank.pab.agpay.res.PayRefundQueryResMsg;
import com.gopay.common.domain.bank.pab.agpay.res.PayRefundResMsg;
import com.gopay.common.domain.bank.pab.agpay.res.PayStatusResMsg;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.FastJsonUtil;
import com.gopay.remote.bank.businesses.PabScanPayService;

/**
 * 
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2017年8月14日
 */
public class ApayPabBankServiceImpl implements PabScanPayService {

	private static Logger logger = LoggerFactory.getLogger(ApayPabBankServiceImpl.class);
	private PabApayHelper aPayPabHelper;
	private String privateKey;
	private String publicKey;

	@Override
	public Object verify(BaseMessage baseMsg) throws GopayException {
		JSONObject respObject = JSONObject.parseObject(baseMsg.getPlainMessage());
		return aPayPabHelper.verify(respObject, baseMsg.getMchKey());
	}

	@Override
	public Object payment(BaseMessage baseMsg) throws GopayException {
		PabTransResMsg<PayOrderResMsg> resMessage = new PabTransResMsg<PayOrderResMsg>();
		String returnStr = null;
		try {
			Map<String, String> param = generateTransParam(baseMsg);
			returnStr = Transport.handlePost((TreeMap<String, String>) param, baseMsg.getPayUrl(), PabConstants.PAMENT);
			logger.info("下单接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {
					// 验签成功
					if (aPayPabHelper.verify(respObject, baseMsg.getMchKey())) {
						//AES解密，并hex2bin					 
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("下单接口返回明文报文为：" + respData);
						PayOrderResMsg orderResMsg = FastJsonUtil.toBean(respData, PayOrderResMsg.class);
						resMessage.setBody(orderResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}
	}

	@Override
	public Object refund(BaseMessage baseMsg) throws GopayException {
		PabTransResMsg<PayRefundResMsg> resMessage = new PabTransResMsg<PayRefundResMsg>();
		String returnStr = null;
		try {
			Map<String, String> param = generateTransRefundParam(baseMsg);
			returnStr = Transport.handlePost((TreeMap<String, String>) param, baseMsg.getPayUrl(), PabConstants.REFUND);			
			logger.info("下单接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				
				if (null != dataStr) {
					if (aPayPabHelper.verifyRefund(respObject, baseMsg.getMchKey(), privateKey,
							publicKey)) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("下单接口返回明文报文为：" + respData);
						PayRefundResMsg refundResMsg = FastJsonUtil.toBean(respData, PayRefundResMsg.class);
						resMessage.setBody(refundResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}

	}

	@Override
	public Object queryOrder(BaseMessage baseMsg) throws GopayException {
		PabTransResMsg<PayStatusResMsg> resMessage = new PabTransResMsg<PayStatusResMsg>();
		String returnStr = null;
		try {
			Map<String, String> param = generateTransParam(baseMsg);
			returnStr = Transport.handlePost((TreeMap<String, String>) param, baseMsg.getQueryUrl(),
					PabConstants.ORDER_QUERY);
			logger.info("订单查询接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {
					// 验签成功
					if (aPayPabHelper.verify(respObject, baseMsg.getMchKey())) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("订单查询返回明文报文为：" + respData);
						PayStatusResMsg orderResMsg = FastJsonUtil.toBean(respData, PayStatusResMsg.class);
						resMessage.setBody(orderResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}
	}

	@Override
	public Object refundQuery(Object msg) throws GopayException {

		PabTransResMsg<PayRefundQueryResMsg> resMessage = new PabTransResMsg<PayRefundQueryResMsg>();
		BaseMessage baseMsg=(BaseMessage)msg;
		String returnStr = null;
		try {
			Map<String, String> param = generateTransParam(baseMsg);
			returnStr = Transport.handlePost((TreeMap<String, String>) param, baseMsg.getQueryUrl(),
					PabConstants.REFUND_QUERY);
			logger.info("退款订单查询接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {
					// 验签成功
					if (aPayPabHelper.verify(respObject, baseMsg.getMchKey())) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("退款订单查询返回明文报文为：" + respData);
						PayRefundQueryResMsg orderResMsg = FastJsonUtil.toBean(respData, PayRefundQueryResMsg.class);
						resMessage.setBody(orderResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}
	
	}

	@Override
	public Object merchantSettled(BaseMessage baseMsg) throws GopayException {

		PabTransResMsg<MerchantAddResMsg> resMessage = new PabTransResMsg<MerchantAddResMsg>();
		String returnStr = null;
		try {
			TreeMap<String, String> getmap = new TreeMap<String, String>();
			String timestamp =System.currentTimeMillis() / 1000 + "";
			getmap.put("open_id", baseMsg.getMerID());
			getmap.put("lang", "zh-cn");
			getmap.put("timestamp", timestamp);
			getmap.put("randStr", RandomStringUtils.randomAlphanumeric(32));

			Map<String, String> param = generateMerchantParam(baseMsg, getmap);

			returnStr = Transport.handleMerchantPost((TreeMap<String, String>) param, getmap, baseMsg.getPayUrl(),
					PabConstants.MERCHANT_SETTLED);

			logger.info("商户入驻接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {
					
					if (aPayPabHelper.verifyMerchant(respObject, publicKey)) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("商户入驻接口返回明文报文为：" + respData);
						MerchantAddResMsg merchantResMsg = FastJsonUtil.toBean(respData, MerchantAddResMsg.class);
						resMessage.setBody(merchantResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}

	}

	@Override
	public Object merchantQuery(BaseMessage msg) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object merchantModify(BaseMessage msg) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getCheckAccountFile(BaseMessage baseMsg) throws GopayException {

		String resMessage = null;
		try {
			TreeMap<String, String> getmap = new TreeMap<String, String>();
			String timestamp = System.currentTimeMillis() / 1000 + "";
			getmap.put("open_id", baseMsg.getMerID());
			getmap.put("lang", "zh-cn");
			getmap.put("timestamp", timestamp);
			getmap.put("randStr", RandomStringUtils.randomAlphanumeric(32));
			Map<String, String> param = generateMerchantParam(baseMsg, getmap);
			resMessage = Transport.handleGetFilePost((TreeMap<String, String>) param, getmap, baseMsg.getPayUrl(),
					PabConstants.GET_ACCT_FILE,baseMsg.getBankOrderType());
			if (!resMessage.isEmpty()) {
				
				return resMessage;
			} else {
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
			}
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}

	}
	@Override
	public Object payOrderCancel(BaseMessage baseMsg) throws GopayException {
		PabTransResMsg<PayCancelResMsg> resMessage = new PabTransResMsg<PayCancelResMsg>();
		String returnStr = null;
		try {
			Map<String, String> param = generateTransRefundParam(baseMsg);
			returnStr = Transport.handlePost((TreeMap<String, String>) param, baseMsg.getPayUrl(), PabConstants.PAYCANCEL);			
			logger.info("撤销订单接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());			
				if (null != dataStr) {
					if (aPayPabHelper.verifyRefund(respObject, baseMsg.getMchKey(), privateKey,
							publicKey)) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("撤销订单接口返回明文报文为：" + respData);
						PayCancelResMsg refundResMsg = FastJsonUtil.toBean(respData, PayCancelResMsg.class);
						resMessage.setBody(refundResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}
	}
	/**
	 * 
	 * 功能描述：构建上送平安银行参数,交易及查询业务
	 *
	 * @param baseMsg
	 * @param tranCode
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月14日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Map<String, String> generateTransParam(BaseMessage baseMsg) throws GopayException {
		TreeMap<String, String> postmap = new TreeMap<String, String>();
		String timestamp = System.currentTimeMillis() / 1000 + "";
		try {
			postmap.put("open_id", baseMsg.getMerID());
			postmap.put("timestamp", timestamp);
			/*
			 * 1 data（JSON）字段内容进行AES加密，再二进制转十六进制(bin2hex)
			 */
			//PabApayHelper aPayPabHelper=new PabApayHelper();
			String data = aPayPabHelper.encrypt(baseMsg.getPlainMessage(), baseMsg.getMchKey());
			postmap.put("data", data);
			/*
			 * 2 请求参数签名 按A~z排序，串联成字符串，先进行sha1加密(小写)，再进行md5加密(小写)，得到签名
			 */
			String signData = aPayPabHelper.handleSign(postmap, baseMsg.getMchKey());
			postmap.put("sign", signData);
			logger.info("pab apay submit param :" + postmap);
		} catch (Exception e) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025);
		}
		return postmap;
	}

	/**
	 * 
	 * 功能描述：构建上送平安银行参数,退款业务
	 *
	 * @param baseMsg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Map<String, String> generateTransRefundParam(BaseMessage baseMsg) throws GopayException {
		TreeMap<String, String> postmap = new TreeMap<String, String>();
		String timestamp = System.currentTimeMillis() / 1000 + "";
		try {
			postmap.put("open_id", baseMsg.getMerID());
			postmap.put("timestamp", timestamp);
			/*
			 * 1 data（JSON）字段内容进行AES加密，再二进制转十六进制(bin2hex)
			 */
			String data = aPayPabHelper.encrypt(baseMsg.getPlainMessage(), baseMsg.getMchKey());
			postmap.put("data", data);
			postmap.put("sign_type", "RSA");
			/*
			 * 2 请求参数签名 按A~z排序，串联成字符串，先进行sha1加密(小写)，再进行md5加密(小写)，得到签名
			 */			
			logger.info("privateKey :=======" + privateKey);
			String signData = aPayPabHelper.handleSignRSA(postmap, baseMsg.getMchKey(), privateKey);
			postmap.put("sign", signData);
			logger.info("pab refund submit param :" + postmap);
		} catch (Exception e) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025);
		}
		return postmap;
	}

	/**
	 * 
	 * 功能描述：构建上送平安银行参数，进件业务
	 *
	 * @param baseMsg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年8月22日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Map<String, String> generateMerchantParam(BaseMessage baseMsg, TreeMap<String, String> getmap)
			throws GopayException {
		TreeMap<String, String> postmap = new TreeMap<String, String>();
		try {
			/*
			 * 1 data（JSON）字段内容进行AES加密，再二进制转十六进制(bin2hex)
			 */
			String data = aPayPabHelper.encrypt(baseMsg.getPlainMessage(), baseMsg.getMchKey());
			postmap.put("data", data);
			/*
			 * 2 请求参数签名 按A~z排序，串联成字符串，先进行sha1加密(小写)，再进行md5加密(小写)，得到签名
			 */
			String signData = aPayPabHelper.handleMerchantSign(getmap, postmap, privateKey);
			postmap.put("sign", signData);
			logger.info("pab refund submit param :" + postmap);
		} catch (Exception e) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025);
		}
		return postmap;
	}

	public PabApayHelper getaPayPabHelper() {
		return aPayPabHelper;
	}

	public void setaPayPabHelper(PabApayHelper aPayPabHelper) {
		this.aPayPabHelper = aPayPabHelper;
	}

	@Override
	public Object merchantOperation(BaseMessage baseMsg) throws GopayException {

		@SuppressWarnings("rawtypes")
		PabTransResMsg resMessage = new PabTransResMsg();
		String returnStr = null;
		try {
			TreeMap<String, String> getmap = new TreeMap<String, String>();
			String timestamp = System.currentTimeMillis() / 1000 + "";
			getmap.put("open_id", baseMsg.getMerID());
			getmap.put("lang", "zh-cn");
			getmap.put("timestamp", timestamp);
			getmap.put("randStr", RandomStringUtils.randomAlphanumeric(32));

			Map<String, String> param = generateMerchantParam(baseMsg, getmap);

			returnStr = Transport.handleMerchantPost((TreeMap<String, String>) param, getmap, baseMsg.getPayUrl(),
					PabConstants.MERCHANT_CONFIG);

			logger.info("商户配置接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {					
					if (aPayPabHelper.verifyMerchant(respObject, publicKey)) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), baseMsg.getMchKey());
						logger.info("商户配置接口返回明文报文为：" + respData);
						MerchantConfig configResMsg = FastJsonUtil.toBean(respData, MerchantConfig.class);
						resMessage.setBody(configResMsg);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
					}
				}
			}else{
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E5327);
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
		}	
	}

	/**
	 * @return 返回 privateKey。
	 */
	public String getPrivateKey() {
		return privateKey;
	}

	/**
	 * @param privateKey 要设置的 privateKey。
	 */
	public void setPrivateKey(String privateKey) {
		this.privateKey = privateKey;
	}

	/**
	 * @return 返回 publicKey。
	 */
	public String getPublicKey() {
		return publicKey;
	}

	/**
	 * @param publicKey 要设置的 publicKey。
	 */
	public void setPublicKey(String publicKey) {
		this.publicKey = publicKey;
	}
}
